package com.zhihaoliang.baseframe.db;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;


import com.google.common.annotations.VisibleForTesting;
import com.zhihaoliang.baseframe.AppExecutors;
import com.zhihaoliang.baseframe.DataGenerator;
import com.zhihaoliang.baseframe.db.converter.DateConverter;
import com.zhihaoliang.baseframe.db.dao.CommentDao;
import com.zhihaoliang.baseframe.db.dao.ProductDao;
import com.zhihaoliang.baseframe.db.entity.CommentEntity;
import com.zhihaoliang.baseframe.db.entity.ProductEntity;
import com.zhihaoliang.baseframe.db.entity.ProductFtsEntity;

import java.util.List;

/**
 * 创建日期：2020-02-24
 * 描述:数据库
 * 作者:支豪亮
 */

@Database(entities = {ProductEntity.class, ProductFtsEntity.class, CommentEntity.class}, version = 2)
@TypeConverters(value = DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {

    private static AppDatabase sInstance;

    public abstract ProductDao productDao();

    public abstract CommentDao commentDao();


    public final MutableLiveData<Boolean> mIsDatebaseCreated = new MutableLiveData<>();
    /**
     * 数据库的名字,这应该是private现在设置为public主要是为了测试VisibleForTesting就是说明这个
     */
    @VisibleForTesting
    public static final String DATABASE_NAME = "basic_sample_db";

    /**
     * 数据库从1版本升级的版本2需要做的东西
     */
    private static final Migration MIGRATION_1_2 = new Migration(1, 2) {

        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `productsFts` USING FTS4(`name` TEXT, `description` TEXT, content=`products`)");
            database.execSQL("INSERT INTO productsFts (`rowid`, `name`, `description`) "
                    + "SELECT `id`, `name`, `description` FROM products");

        }
    };

    public static AppDatabase getInstance(final Context context, final AppExecutors executors) {
        if (sInstance == null) {
            synchronized (AppDatabase.class) {
                if (sInstance == null) {
                   sInstance = buildDatabase(context.getApplicationContext(),executors);
                   sInstance.updateDatabaseCreated(context);
                }
            }
        }
        return sInstance;
    }

    public MutableLiveData<Boolean> getDatebaseCreated() {
        return mIsDatebaseCreated;
    }

    private static AppDatabase buildDatabase(final Context appContext, final AppExecutors executors) {
        return Room.databaseBuilder(appContext, AppDatabase.class, DATABASE_NAME).
                addMigrations(MIGRATION_1_2)
                .addCallback(new Callback() {
                    @Override
                    public void onCreate(@NonNull SupportSQLiteDatabase db) {
                        super.onCreate(db);
                        executors.getDiskIO().execute(() -> {
                            //添加演示模拟长时间的操作
                            addDelay();
                            //生成预填充数据
                            AppDatabase database = AppDatabase.getInstance(appContext, executors);
                            List<ProductEntity> products = DataGenerator.generatorProducts();
                            List<CommentEntity> comments = DataGenerator.generatorComments(products);
                            insertData(database, products, comments);
                            //
                            database.setDatabaseCreated();
                        });
                    }
                }).build();
    }

    private static void insertData(final AppDatabase database,final List<ProductEntity> products,final List<CommentEntity> comments){
        database.runInTransaction(()->{
            database.productDao().insertAll(products);
            database.commentDao().insertAll(comments);
        });
    }


    private void updateDatabaseCreated(final Context context){
        if(context.getDatabasePath(DATABASE_NAME).exists()){
            setDatabaseCreated();
        }
    }

    private void setDatabaseCreated(){
        mIsDatebaseCreated.postValue(true);
    }

    private static void addDelay() {
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
